package vip.xiaonuo.common.util;

import cn.hutool.http.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Enumeration;

@Slf4j
public class EBusPayUtil {


    private static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
    private static final String SHA1withRSA = "SHA1withRSA";

    private static final String URL = "https://pay.abchina.com/ebus/ReceiveMerchantTrxReqServlet";

    /**
     * 加签方法
     *
     * @param merchantPrivateKey         商户私钥 (PKCS#12格式)
     * @param merchantPrivateKeyPassword 商户私钥密码
     * @param message                    请求报文原始数据
     * @return 加签后的请求报文
     */
    public static String signRequest(byte[] merchantPrivateKey, String merchantPrivateKeyPassword, String message) throws Exception {
        // 获取签名实例（推荐 SHA256withRSA）
        Signature signature = Signature.getInstance(SHA1withRSA);
        // 加载 PKCS12 证书（无需额外 Provider）
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(new ByteArrayInputStream(merchantPrivateKey), merchantPrivateKeyPassword.toCharArray());
        Enumeration<String> aliases = keyStore.aliases();
        String alias = null;
        while (aliases.hasMoreElements()) {
            alias = aliases.nextElement();
            break;
        }
        if (alias == null) {
            throw new Exception("未找到有效密钥别名");
        }

        // 获取私钥
        PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, merchantPrivateKeyPassword.toCharArray());

        // 初始化签名
        signature.initSign(privateKey);
        signature.update(message.getBytes(StandardCharsets.UTF_8));

        // 生成 Base64 编码的签名值
        String signatureInBase64 = java.util.Base64.getEncoder().encodeToString(signature.sign());

        // 构造带签名的请求报文
        return String.format(
                "{\"Message\":%s,\"Signature-Algorithm\":\"%s\",\"Signature\":\"%s\"}",
                message,
                SIGNATURE_ALGORITHM,
                signatureInBase64
        );
    }


    /**
     * 验签方法
     *
     * @param signatureAlgorithm 返回报文中的 Signature-Algorithm 字段对应的值
     * @param signature          返回报文中的 Signature 字段对应的值（Base64 编码）
     * @param message            返回报文中的 Message 字段原始 JSON 数据
     * @param trustPayCert       平台证书字节数组（X.509 格式）
     * @return true: 验签成功；false: 验签失败
     */
    public static boolean verifyResponse(String signatureAlgorithm, String signature, String message, byte[] trustPayCert) throws Exception {
        // 可选：根据 signatureAlgorithm 判断是否接受该算法
        if (!signatureAlgorithm.equals(SHA1withRSA) && !signatureAlgorithm.equals(SIGNATURE_ALGORITHM)) {
            throw new IllegalArgumentException("不支持的签名算法: " + signatureAlgorithm);
        }
        // 加载公钥证书
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        Certificate certificate = certFactory.generateCertificate(new ByteArrayInputStream(trustPayCert));

        // 初始化签名对象
        Signature signatureInstance = Signature.getInstance(signatureAlgorithm);
        signatureInstance.initVerify(certificate);
        signatureInstance.update(message.getBytes("GBK"));

        // 解码 Base64 签名并验证
        byte[] signatureInBytes = Base64.decodeBase64(signature.getBytes("GBK"));
        return signatureInstance.verify(signatureInBytes);
    }

    /**
     * 验签方法
     *
     * @param signatureAlgorithm 返回报文中的 Signature-Algorithm 字段对应的值
     * @param signature          返回报文中的 Signature 字段对应的值（Base64 编码）
     * @param message            返回报文中的 Message 字段原始 JSON 数据
     * @param merchantPrivateKey       平台证书字节数组（X.509 格式）
     * @return true: 验签成功；false: 验签失败
     */
    public static boolean verifyResponse(String signatureAlgorithm, String signature, String message, String merchantPrivateKey) throws Exception {
        return verifyResponse(signatureAlgorithm, signature, message, readFile(merchantPrivateKey));
    }


    public static byte[] readFile(String filePath) {
        File file = new File(filePath);
        byte[] fileContent = null;
        try {
            FileInputStream fin = new FileInputStream(file);
            fileContent = new byte[(int) file.length()];
            fin.read(fileContent);

        } catch (FileNotFoundException e) {
            System.out.println("File not found" + e);
        } catch (IOException ioe) {
            System.out.println("Exception while reading the file " + ioe);
        }
        return fileContent;
    }

    /**
     * 请求
     *
     * @param merchantPrivateKey         商户私钥 (PKCS#12格式)
     * @param merchantPrivateKeyPassword 商户私钥密码
     * @param message                    请求报文原始数据
     * @return 响应报文
     */
    public static String send(String merchantPrivateKey, String merchantPrivateKeyPassword, String message) throws Exception {
        String request = signRequest(readFile(merchantPrivateKey), merchantPrivateKeyPassword, message);
        log.info("请求报文：{}", request);
        String body = HttpUtil.createPost(URL).body(request)
                .execute().body();
        log.info("响应报文：{}", body);
        return body;
    }

}
